package com.leyou.user.service;

import com.leyou.common.constant.LyConstant;
import com.leyou.common.constant.MQConstants;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;

import com.leyou.user.entity.HisImgs;
import com.leyou.user.entity.User;
import com.leyou.user.entity.UserInfo;
import com.leyou.user.mapper.HisImageMapper;
import com.leyou.user.mapper.UserInfoMapper;
import com.leyou.user.mapper.UserMapper;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import sun.misc.BASE64Decoder;
import tk.mybatis.mapper.entity.Example;

import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Transactional
public class UserService {
    @Autowired
    HisImageMapper hisImageMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private BCryptPasswordEncoder encoder;

    @Autowired
    UserInfoMapper userInfoMapper;

    public Boolean checkUsernameOrPhone(String data, Integer type) {
        //创建一个条件对象
        User record = new User();
        switch (type){
            case 1:
                record.setUsername(data);//按照用户名做查询
                break;
            case 2:
                record.setPhone(data);//按照手机号做查询
                break;
            default:
                throw new LyException(ExceptionEnum.INVALID_PARAM_ERROR);
        }
        //根据条件查询数据量
        int count = userMapper.selectCount(record);
        //如果是0条，表示不存在，就可用
        return count==0;
    }

    public void sendCheckCode(String phone) {
        String key = LyConstant.CHECK_CODE_PRE+phone;
        //生成六位数字验证码
        String code = RandomStringUtils.randomNumeric(6);
        //先存入redis中，过期时间2小时
        redisTemplate.opsForValue().set(key, code, 2, TimeUnit.HOURS);
        //封装一个发送MQ队列的对象
        Map<String, String> msgMap = new HashMap<>();
        msgMap.put("phone", phone);
        msgMap.put("code", code);
        //向消息队列中发送一个消息
        amqpTemplate.convertAndSend(MQConstants.Exchange.SMS_EXCHANGE_NAME,
                MQConstants.RoutingKey.VERIFY_CODE_KEY, msgMap);
    }

    public void register(User user, String code) {
        //获取redis中的验证码
        String redisCode = redisTemplate.opsForValue().get(LyConstant.CHECK_CODE_PRE + user.getPhone());
        //查看用户输入的验证码是否正确
        if(!StringUtils.equals(code, redisCode)){
            throw new LyException(ExceptionEnum.INVALID_VERIFY_CODE);
        }
        //密码加密
        user.setPassword(encoder.encode(user.getPassword()));
        //保存数据
        int count = userMapper.insertSelective(user);
        if(count==0){
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    public User findUserByUsernameAndPassword(String username, String password) {
        //先根据用户名做查询
        User record = new User();
        record.setUsername(username);
        User user = userMapper.selectOne(record);
        if (user==null){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        //比对密码是否正确
        if(!encoder.matches(password, user.getPassword())){
            throw new LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
        return user;
    }

    public UserInfo getUserInfo(Long userId) {
        //根据userId查询用户信息
        Example example = new Example(UserInfo.class);
        example.createCriteria().andEqualTo("userId",userId);
        UserInfo userInfo = userInfoMapper.selectOneByExample(example);
        return userInfo;
    }

    public void saveUserInfo(UserInfo userInfo, String formData)throws Exception {
        Example example = new Example(UserInfo.class);
        example.createCriteria().andEqualTo("userId",userInfo.getUserId());
        userInfoMapper.deleteByExample(example);
        String imageUrl=null;
        if (StringUtils.isNotBlank(formData)){
            String[] split = formData.split(",");
            String img = split[1];
            imageUrl = Base64ToImage(img);
            userInfo.setImage(imageUrl);
        }
        userInfoMapper.insertSelective(userInfo);

        UserInfo one = userInfoMapper.selectOneByExample(example);
        String image=one.getImage();
        if(StringUtils.isNotBlank(image)){
            Example hisExample = new Example(HisImgs.class);
            example.createCriteria().andEqualTo("userId",userInfo.getUserId());
            List<HisImgs> hisImgsList = hisImageMapper.selectByExample(hisExample);
            List<String> list = hisImgsList.stream().map(HisImgs::getHisImage).collect(Collectors.toList());

            if( !list.contains(image)){
                HisImgs hisImgs = new HisImgs();
                hisImgs.setHisImage(image);
                hisImgs.setUserId(userInfo.getUserId());
                hisImageMapper.insertSelective(hisImgs);
            }
        }



    }


    /**
     * base64字符串转换成图片  对字节数组字符串进行Base64解码并生成图片
     * @param imgStr        base64字符串
     *
     * @return返回图片的nginx访问路径
     */
    public  String Base64ToImage(String imgStr ) {
        String fileName=UUID.randomUUID()+".jpg";
        String imgFilePath=LyConstant.HEAD_IMG_FILE+fileName;
        String imageUrl=LyConstant.HEAD_IMG_URL+fileName;
        // 图像数据为空
        if (StringUtils.isEmpty(imgStr)){

        }


        BASE64Decoder decoder = new BASE64Decoder();

        try(OutputStream out=new FileOutputStream(new File(imgFilePath))){
            // Base64解码
            byte[] b = decoder.decodeBuffer(imgStr);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
            out.write(b);
            out.flush();
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.FILE_UPLOAD_ERROR);
        }
        return imageUrl;
    }
}
